/*
 * Copyright (C) 2014-2016 Qiujuer <qiujuer@live.cn>
 * WebSite http://www.qiujuer.net
 * Created 12/15/2015
 * Changed 05/10/2016
 * Version 2.0.0
 * Author Qiujuer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.qiujuer.genius.ui.drawable;


import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AbsButton;
import ohos.agp.components.Checkbox;
import ohos.agp.components.Component;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;

import net.qiujuer.genius.ui.widget.ValueAnimator;

/**
 * This is CheckBox drawable
 * The draw is Circle by animation.
 *
 * @since 2021-05-13
 */
public class CircleCheckDrawable extends ShapeElement implements Component.DrawTask, AbsButton.CheckedStateChangedListener {
    private ValueAnimator checkAnim, unCheckAnim;
    private Color enableCheckColor = Color.GRAY;
    private Color enableUncheckColor = Color.GRAY;
    private Color unableCheckColor = Color.GRAY;
    private Color unableUncheckColor = Color.GRAY;
    private int borderSize = 4;
    private int intervalSize = 16;
    private final Paint backgroundPaint = new Paint();
    private final Paint foregroundPaint = new Paint();
    private int degrees = 0;
    private float alpha = 0;
    private static final int duration = 250;
    private boolean isEnabled = true;
    private final Checkbox checkbox;

    /**
     * 默认构造
     *
     * @param checkbox 作用于的控件
     */
    public CircleCheckDrawable(Checkbox checkbox) {
        this.checkbox = checkbox;
        setBounds(0, 0, 33, 0);
        backgroundPaint.setStyle(Paint.Style.STROKE_STYLE);
        backgroundPaint.setStrokeWidth(borderSize);
        backgroundPaint.setAntiAlias(true);
        backgroundPaint.setColor(enableUncheckColor);
        foregroundPaint.setStyle(Paint.Style.FILL_STYLE);
        foregroundPaint.setAntiAlias(true);
        foregroundPaint.setColor(enableCheckColor);
    }

    @Override
    public void onCheckedChanged(AbsButton absButton, boolean checked) {
        setCheckState(checked);
    }

    /**
     * 设置是否可用
     *
     * @param enabled 是否可用
     */
    public void setEnabled(boolean enabled) {
        isEnabled = enabled;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        float vCenter = component.getHeight() / 2f;
        // 1.draw background bound
        if (isEnabled) {
            backgroundPaint.setColor(enableUncheckColor);
        } else {
            backgroundPaint.setColor(unableUncheckColor);
        }
        canvas.drawCircle(vCenter, vCenter, vCenter - borderSize, backgroundPaint);

        // 2.draw foreground
        if (isEnabled) {
            foregroundPaint.setColor(enableCheckColor);
        } else {
            foregroundPaint.setColor(unableCheckColor);
        }
        foregroundPaint.setAlpha(alpha);
        canvas.drawCircle(vCenter, vCenter, vCenter - intervalSize, foregroundPaint);

        // 4.draw foreground bound
        if (isEnabled) {
            backgroundPaint.setColor(enableCheckColor);
        } else {
            backgroundPaint.setColor(unableCheckColor);
        }
        canvas.drawArc(new RectFloat(borderSize, borderSize,
                borderSize + 2 * (vCenter - borderSize), borderSize + 2 * (vCenter - borderSize)),
            new Arc(0, degrees, false), backgroundPaint);
    }

    /**
     * 设置选中状态
     *
     * @param checked 是否选中
     */
    public void setCheckState(boolean checked) {
        if (checked) {
            check();
        } else {
            uncheck();
        }
    }

    private void check() {
        if (checkAnim == null) {
            checkAnim = ValueAnimator.ofFloat(0, 1);
            checkAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(AnimatorValue animatorValue, float fraction, Object animatedValue) {
                    float value = (float) animatedValue;
                    degrees = (int) (360 * value);
                    alpha = value;
                    checkbox.invalidate();
                }
            });
            checkAnim.setDuration(duration);
        }
        if (checkAnim.isRunning()) {
            return;
        }
        if (unCheckAnim != null && unCheckAnim.isRunning()) {
            unCheckAnim.end();
        }
        checkAnim.start();
    }

    private void uncheck() {
        if (unCheckAnim == null) {
            unCheckAnim = ValueAnimator.ofFloat(1, 0);
            unCheckAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(AnimatorValue animatorValue, float fraction, Object animatedValue) {
                    float value = (float) animatedValue;
                    degrees = (int) (360 * value);
                    alpha = value;
                    checkbox.invalidate();
                }
            });
            unCheckAnim.setDuration(duration);
        }
        if (unCheckAnim.isRunning()) {
            return;
        }
        if (checkAnim != null && checkAnim.isRunning()) {
            checkAnim.end();
        }
        unCheckAnim.start();
    }

    /**
     * 设置可用选中颜色
     *
     * @param color 颜色
     */
    public void setEnableCheckColor(Color color) {
        this.enableCheckColor = color;
    }

    /**
     * 设置可用非选中颜色
     *
     * @param color 颜色
     */
    public void setEnableUncheckColor(Color color) {
        this.enableUncheckColor = color;
    }

    /**
     * 设置不可用选中颜色
     *
     * @param color
     */
    public void setUnableCheckColor(Color color) {
        this.unableCheckColor = color;
    }

    /**
     * 设置不可用非选中颜色
     *
     * @param color 颜色
     */
    public void setUnableUncheckColor(Color color) {
        this.unableUncheckColor = color;
    }

    /**
     * 设置外圈宽度
     *
     * @param borderSize 宽度
     */
    public void setBorderSize(int borderSize) {
        this.borderSize = borderSize;
        backgroundPaint.setStrokeWidth(borderSize);
    }

    /**
     * 设置外圈和内圆间距
     *
     * @param intervalSize 间距
     */
    public void setIntervalSize(int intervalSize) {
        this.intervalSize = intervalSize;
    }
}
